#include "ws2812_bsp.h"

// TIM3和DMA句柄
TIM_HandleTypeDef htim3;
DMA_HandleTypeDef hdma_tim3;

/**
 * @brief void DMA1_Stream4_IRQHandler(void) 
 * @brief DMA传输完成中断处理
 */
void DMA1_Stream4_IRQHandler(void) 
{
    // 只保留错误中断处理
    if (__HAL_DMA_GET_FLAG(&hdma_tim3, DMA_FLAG_TEIF0_4)) {
        __HAL_DMA_CLEAR_FLAG(&hdma_tim3, DMA_FLAG_TEIF0_4);
    }
    
    // 处理DMA中断
    HAL_DMA_IRQHandler(&hdma_tim3);
    
    // 传输完成后重置状态
    if (__HAL_DMA_GET_FLAG(&hdma_tim3, DMA_FLAG_TCIF0_4)) {
        __HAL_DMA_CLEAR_FLAG(&hdma_tim3, DMA_FLAG_TCIF0_4);
        hdma_tim3.State = HAL_DMA_STATE_READY;
    }
}


/**
 * @brief TIM PWM DMA传输完成回调函数
 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM3) 
	{
        // 停止DMA传输
        HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_1);
        
        // 手动重置DMA状态
        hdma_tim3.State = HAL_DMA_STATE_READY;
        
        // 清除所有DMA标志
        __HAL_DMA_CLEAR_FLAG(&hdma_tim3, DMA_FLAG_TCIF0_4 | DMA_FLAG_TEIF0_4 | 
                             DMA_FLAG_HTIF0_4 | DMA_FLAG_DMEIF0_4 | DMA_FLAG_FEIF0_4);
    }
}


/**
 * @brief PWM初始化 (TIM3 CH1 - PA6)
 */
static void PWM_Init(void) 
{
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    
    // 使能TIM3时钟
    __HAL_RCC_TIM3_CLK_ENABLE();
    
    // 定时器基础配置
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 0;
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = PWM_PERIOD;
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_StatusTypeDef status = HAL_TIM_PWM_Init(&htim3);
    if (status != HAL_OK) 
    {
        printf("[ERROR] TIM PWM Init Failed: %d\r\n", status);
        return;
    }
    
    // 配置主模式
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    status = HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
    if (status != HAL_OK)
    {
        printf("[ERROR] TIM Master Config Failed: %d\r\n", status);
        return;
    }

    // PWM通道1配置 (PA6)
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    status = HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
    if (status != HAL_OK) 
    {
        printf("[ERROR] TIM PWM Channel Config Failed: %d\r\n", status);
        return;
    }

    // GPIO配置（PA6复用功能）
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // PA6: TIM3_CH1 (AF2)
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    printf("[INFO] PWM Initialized Successfully\r\n");
}

/**
 * @brief DMA初始化
 */
static void DMA_Init(void) 
{
    // 使能DMA1时钟
    __HAL_RCC_DMA1_CLK_ENABLE();

    // 通道1 DMA配置 (TIM3_CH1 -> DMA1 Stream4)
    hdma_tim3.Instance = DMA1_Stream4;
    hdma_tim3.Init.Channel = DMA_CHANNEL_5;
    hdma_tim3.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim3.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim3.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_tim3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_tim3.Init.Mode = DMA_NORMAL;
    hdma_tim3.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_tim3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_StatusTypeDef status = HAL_DMA_Init(&hdma_tim3);
    if (status != HAL_OK) 
    {
        printf("[ERROR] DMA Init Failed: %d\r\n", status);
        return;
    }

    // 链接DMA到TIM3通道1
    __HAL_LINKDMA(&htim3, hdma[TIM_DMA_ID_CC1], hdma_tim3);
    
    // 配置DMA中断
    HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
    
    printf("[INFO] DMA Initialized Successfully\r\n");
}


/**
 * @brief 启动WS2812数据传输
 */
void WS2812_Start_Transfer(uint16_t *data, uint32_t size)
{
    // 确保DMA空闲
    if (HAL_DMA_GetState(&hdma_tim3) == HAL_DMA_STATE_BUSY) {
        printf("[WARN] DMA Busy, Skipping Transfer\r\n");
        return;
    }
    
    // 启动PWM DMA传输
    HAL_StatusTypeDef status = HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, 
                                                   (uint32_t *)data, size);
    if (status != HAL_OK) 
    {
        printf("[ERROR] TIM PWM Start DMA Failed: %d\r\n", status);
    }
}


/**
 * @brief void ws2812_init(void) 
 * @brief ws2812驱动初始化
 * @param  无
 * @return 无
 */
void ws2812_bsp_init(void)
{
	PWM_Init();
	DMA_Init();
}


